package com.blacktech.dbu.core.controller;

import com.blacktech.dbu.core.dto.SearchRequest;
import com.blacktech.dbu.core.exception.BusinessException;
import com.blacktech.dbu.core.response.PageResponse;
import com.blacktech.dbu.core.response.ResponseCode;
import com.blacktech.dbu.core.util.SearchableFieldsUtils;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.persistence.criteria.*;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 基础CRUD Controller抽象类
 * 提供标准的增删改查接口模板
 * 响应由GlobalResponseHandler统一包装
 *
 * @param <T>  实体类型
 * @param <ID> 主键类型
 * @author Yanyunsong
 */
public abstract class BaseCrudController<T, ID> {

    @Autowired
    protected SearchableFieldsUtils searchableFieldsUtils;

    /**
     * 创建实体
     */
    @PostMapping
    public T create(@RequestBody T entity) {
        return doCreate(entity);
    }

    /**
     * 根据ID获取实体
     */
    @GetMapping("/{id}")
    public T getById(@PathVariable ID id) {
        T entity = doGetById(id);
        if (entity == null) {
            throw new BusinessException(ResponseCode.NOT_FOUND.getCode(), "资源不存在");
        }
        return entity;
    }

    /**
     * 获取所有实体（分页）
     */
    @GetMapping
    public PageResponse<T> getAll(@RequestParam(defaultValue = "0") int page,
                                  @RequestParam(defaultValue = "20") int size,
                                  @RequestParam(defaultValue = "id") String sortBy,
                                  @RequestParam(defaultValue = "asc") String sortDir) {

        Sort.Direction direction = "desc".equalsIgnoreCase(sortDir) ? Sort.Direction.DESC : Sort.Direction.ASC;
        Pageable pageable = PageRequest.of(page, size, Sort.by(direction, sortBy));

        Page<T> entityPage = doGetAll(pageable);
        return PageResponse.of(entityPage);
    }

    /**
     * 获取所有实体（不分页）
     */
    @GetMapping("/all")
    public List<T> getAllWithoutPagination() {
        return doGetAllWithoutPagination();
    }

    /**
     * 更新实体
     */
    @PutMapping("/{id}")
    public T update(@PathVariable ID id, @RequestBody T entity) {
        T updatedEntity = doUpdate(id, entity);
        if (updatedEntity == null) {
            throw new BusinessException(ResponseCode.NOT_FOUND.getCode(), "资源不存在");
        }
        return updatedEntity;
    }

    /**
     * 删除实体
     */
    @DeleteMapping("/{id}")
    public String delete(@PathVariable ID id) {
        boolean deleted = doDelete(id);
        if (!deleted) {
            throw new BusinessException(ResponseCode.NOT_FOUND.getCode(), "资源不存在");
        }
        return "删除成功";
    }

    /**
     * 批量删除实体
     */
    @DeleteMapping("/batch")
    public String batchDelete(@RequestBody List<ID> ids) {
        int deletedCount = doBatchDelete(ids);
        return "成功删除 " + deletedCount + " 条记录";
    }

    /**
     * 高级搜索实体
     * 支持关键词、精确匹配、模糊匹配等多种搜索方式
     */
    @PostMapping("/search")
    @Operation(summary = "高级搜索实体", description = "支持关键词、精确匹配、模糊匹配、范围查询等多种搜索方式")
    public PageResponse<T> searchEntities(@Valid @RequestBody SearchRequest searchRequest) {
        // 构建搜索条件
        Specification<T> specification = buildSearchSpecification(searchRequest);

        // 构建分页和排序参数
        Pageable pageable = buildPageable(searchRequest);

        // 执行搜索
        Page<T> result = doSearch(specification, pageable);

        return PageResponse.of(result);
    }

    /**
     * 构建搜索的Specification
     * 子类可以重写此方法来添加自定义搜索逻辑
     */
    protected Specification<T> buildSearchSpecification(SearchRequest searchRequest) {
        return (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();

            // 构建关键词搜索条件
            Specification<T> keywordSpec = buildKeywordSpecification(searchRequest.getKeyword());
            if (keywordSpec != null) {
                Predicate keywordPredicate = keywordSpec.toPredicate(root, query, criteriaBuilder);
                if (keywordPredicate != null) {
                    predicates.add(keywordPredicate);
                }
            }

            // 构建精确匹配条件
            Specification<T> exactMatchSpec = buildExactMatchSpecification(searchRequest.getExactMatches());
            if (exactMatchSpec != null) {
                Predicate exactMatchPredicate = exactMatchSpec.toPredicate(root, query, criteriaBuilder);
                if (exactMatchPredicate != null) {
                    predicates.add(exactMatchPredicate);
                }
            }

            // 构建模糊匹配条件
            Specification<T> fuzzyMatchSpec = buildFuzzyMatchSpecification(searchRequest.getFuzzyMatches());
            if (fuzzyMatchSpec != null) {
                Predicate fuzzyMatchPredicate = fuzzyMatchSpec.toPredicate(root, query, criteriaBuilder);
                if (fuzzyMatchPredicate != null) {
                    predicates.add(fuzzyMatchPredicate);
                }
            }

            // 构建范围查询条件
            Specification<T> rangeSpec = buildRangeSpecification(searchRequest.getRangeValues());
            if (rangeSpec != null) {
                Predicate rangePredicate = rangeSpec.toPredicate(root, query, criteriaBuilder);
                if (rangePredicate != null) {
                    predicates.add(rangePredicate);
                }
            }

            // 允许子类添加额外的自定义条件
            Predicate customPredicate = addCustomSearchConditions(searchRequest, root, query, criteriaBuilder);
            if (customPredicate != null) {
                predicates.add(customPredicate);
            }

            return predicates.isEmpty() ? criteriaBuilder.conjunction() : criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }

    /**
     * 构建关键词搜索条件
     */
    protected Specification<T> buildKeywordSpecification(String keyword) {
        return (root, query, criteriaBuilder) -> {
            if (keyword == null || keyword.trim().isEmpty()) {
                return criteriaBuilder.conjunction();
            }

            // 使用工具类构建关键词搜索条件
            return searchableFieldsUtils.buildKeywordPredicate(
                    root, query, criteriaBuilder, getEntityClass(), keyword);
        };
    }

    /**
     * 构建精确匹配条件
     */
    protected Specification<T> buildExactMatchSpecification(Map<String, Object> exactMatches) {
        return (root, query, criteriaBuilder) -> {
            if (exactMatches == null || exactMatches.isEmpty()) {
                return criteriaBuilder.conjunction();
            }

            List<Predicate> predicates = new ArrayList<>();

            for (Map.Entry<String, Object> entry : exactMatches.entrySet()) {
                String field = entry.getKey();
                Object value = entry.getValue();

                if (value != null) {
                    try {
                        predicates.add(criteriaBuilder.equal(root.get(field), value));
                    } catch (IllegalArgumentException e) {
                        // 如果字段不存在，跳过
                        continue;
                    }
                }
            }

            return predicates.isEmpty() ? criteriaBuilder.conjunction()
                    : criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }

    /**
     * 构建模糊匹配条件
     */
    protected Specification<T> buildFuzzyMatchSpecification(Map<String, String> fuzzyMatches) {
        return (root, query, criteriaBuilder) -> {
            if (fuzzyMatches == null || fuzzyMatches.isEmpty()) {
                return criteriaBuilder.conjunction();
            }

            List<Predicate> predicates = new ArrayList<>();

            for (Map.Entry<String, String> entry : fuzzyMatches.entrySet()) {
                String field = entry.getKey();
                String value = entry.getValue();

                if (value != null && !value.trim().isEmpty()) {
                    try {
                        Expression<String> fieldExpression = root.get(field).as(String.class);
                        predicates.add(criteriaBuilder.like(
                                criteriaBuilder.lower(fieldExpression),
                                "%" + value.toLowerCase().trim() + "%"));
                    } catch (IllegalArgumentException e) {
                        // 如果字段不存在或无法转换为String，跳过
                        continue;
                    }
                }
            }

            return predicates.isEmpty() ? criteriaBuilder.conjunction()
                    : criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }

    /**
     * 构建范围查询条件
     */
    protected Specification<T> buildRangeSpecification(Map<String, SearchRequest.RangeValue> rangeValues) {
        return (root, query, criteriaBuilder) -> {
            if (rangeValues == null || rangeValues.isEmpty()) {
                return criteriaBuilder.conjunction();
            }

            List<Predicate> predicates = new ArrayList<>();

            for (Map.Entry<String, SearchRequest.RangeValue> entry : rangeValues.entrySet()) {
                String field = entry.getKey();
                SearchRequest.RangeValue rangeValue = entry.getValue();

                if (rangeValue != null) {
                    try {
                        if (rangeValue.getMin() != null) {
                            Expression<Comparable> fieldExpression = root.get(field).as(Comparable.class);
                            Object minValue = rangeValue.getMin();

                            Predicate minPredicate = rangeValue.isIncludeMin()
                                    ? criteriaBuilder.greaterThanOrEqualTo(fieldExpression, (Comparable) minValue)
                                    : criteriaBuilder.greaterThan(fieldExpression, (Comparable) minValue);
                            predicates.add(minPredicate);
                        }

                        if (rangeValue.getMax() != null) {
                            Expression<Comparable> fieldExpression = root.get(field).as(Comparable.class);
                            Object maxValue = rangeValue.getMax();

                            Predicate maxPredicate = rangeValue.isIncludeMax()
                                    ? criteriaBuilder.lessThanOrEqualTo(fieldExpression, (Comparable) maxValue)
                                    : criteriaBuilder.lessThan(fieldExpression, (Comparable) maxValue);
                            predicates.add(maxPredicate);
                        }
                    } catch (IllegalArgumentException | ClassCastException e) {
                        // 如果字段不存在或类型不匹配，跳过
                        continue;
                    }
                }
            }

            return predicates.isEmpty() ? criteriaBuilder.conjunction()
                    : criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }

    /**
     * 构建Pageable对象
     */
    protected Pageable buildPageable(SearchRequest searchRequest) {
        // 处理分页参数
        int page = searchRequest.getPage();
        int size = searchRequest.getSize();

        // 处理排序参数
        if (searchRequest.getSortFields() == null || searchRequest.getSortFields().isEmpty()) {
            return PageRequest.of(page, size, Sort.by(Sort.Direction.ASC, "id"));
        }

        // 构建多字段排序
        List<Sort.Order> orders = new ArrayList<>();
        for (SearchRequest.SortField sortField : searchRequest.getSortFields()) {
            String field = sortField.getField();
            String direction = sortField.getDirection();

            if (field != null && !field.trim().isEmpty()) {
                Sort.Direction sortDirection = "desc".equalsIgnoreCase(direction)
                        ? Sort.Direction.DESC : Sort.Direction.ASC;
                orders.add(new Sort.Order(sortDirection, field.trim()));
            }
        }

        if (orders.isEmpty()) {
            return PageRequest.of(page, size, Sort.by(Sort.Direction.ASC, "id"));
        }

        return PageRequest.of(page, size, Sort.by(orders));
    }

    // 抽象方法，由具体Controller实现

    /**
     * 执行创建操作
     */
    protected abstract T doCreate(T entity);

    /**
     * 根据ID获取实体
     */
    protected abstract T doGetById(ID id);

    /**
     * 分页获取所有实体
     */
    protected abstract Page<T> doGetAll(Pageable pageable);

    /**
     * 获取所有实体（不分页）
     */
    protected abstract List<T> doGetAllWithoutPagination();

    /**
     * 更新实体
     */
    protected abstract T doUpdate(ID id, T entity);

    /**
     * 删除实体
     */
    protected abstract boolean doDelete(ID id);

    /**
     * 批量删除实体
     */
    protected abstract int doBatchDelete(List<ID> ids);

    /**
     * 执行搜索操作
     */
    protected abstract Page<T> doSearch(Specification<T> specification, Pageable pageable);

    /**
     * 获取实体类型
     * 子类必须实现此方法以指定具体的实体类型
     */
    protected abstract Class<T> getEntityClass();

    /**
     * 添加自定义搜索条件
     * 子类可以重写此方法来添加特定的搜索逻辑，如权限过滤等
     *
     * @param searchRequest   搜索请求
     * @param root            查询根对象
     * @param query           查询对象
     * @param criteriaBuilder 条件构建器
     * @return 自定义搜索条件的Predicate，如果没有额外条件则返回null
     */
    protected Predicate addCustomSearchConditions(
            SearchRequest searchRequest,
            Root<T> root,
            CriteriaQuery<?> query,
            CriteriaBuilder criteriaBuilder) {
        // 默认不添加额外的搜索条件
        return null;
    }
}